#ifndef MODEL_H
#define MODEL_H

#include <sys/types.h>
#include <netinet/in.h>

#include "queue.h"

struct flowset;
struct flow_model;
struct packet_model;
struct variable;
typedef struct flowset_model {
  TAILQ_HEAD(,flow_model) flows;
  int n_flows;
  TAILQ_HEAD(,packet_model) packets;
  int n_packets;
  TAILQ_HEAD(,variable) variables;
  struct flowset *references[2];
} flowset_model_t;

flowset_model_t *flowset_pair_flows(struct flowset *, struct flowset *);

typedef enum {
  PRIMARY_FLOW,
  SECONDARY_FLOW,
} flow_model_type_e;

struct flow;
struct variable;
typedef struct flow_model {
  struct timeval relative_start;
  struct sockaddr_in connector, connectee;
  struct variable *connector_port, *connectee_port;
  flow_model_type_e type;
  int protocol;
  TAILQ_HEAD(,packet_model) packets;
  struct flow *references[2];
  TAILQ_ENTRY(flow_model) next;
} flow_model_t;

struct chunked_packets;
void flowset_analyze(flowset_model_t *, struct chunked_packets *,
  struct chunked_packets *);

struct chunk;
struct chunked_packet;
typedef struct packet_model {
  struct timeval relative_start;
  TAILQ_HEAD(,chunk) chunks;
  struct chunked_packet *references[2];
  TAILQ_ENTRY(packet_model) next_by_flow;
  TAILQ_ENTRY(packet_model) next_by_time;

  flow_model_t *flow;
} packet_model_t;

typedef enum {
  CONSTANT,
  VARIABLE,
  INSTANCE,
} chunk_type_e;

typedef struct usage {
  quark_t *instance;
  TAILQ_ENTRY(usage) next;
} usage_t;

typedef struct variable {
  int id;
  quark_t *references[2];
  TAILQ_HEAD(,usage) usages;
  TAILQ_ENTRY(variable) next;
} variable_t;

typedef struct chunk {
  chunk_type_e type;
  union {
    quark_t constant_quark;
    variable_t variable_quark;
    variable_t *instance;
  } _u;
  TAILQ_ENTRY(chunk) next;
} chunk_t;

#endif /* MODEL_H */
